/* Copyright (c) 2021, National University of Defense Technology. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "par_multivector.h"

namespace YHAMG
{

Par_MultiVector::Par_MultiVector()
	: comm(MPI_COMM_SELF),
	num_vectors(0)
{
}

Par_MultiVector::Par_MultiVector(MPI_Comm _comm)
	: comm(_comm),
	num_vectors(0)
{
}

Par_MultiVector::Par_MultiVector(MPI_Comm _comm, int _num_vectors, int Loc_size, double* Loc_values, int Loc_ref)
	: comm(_comm),
	num_vectors(_num_vectors),
	Loc(_num_vectors, Loc_size, Loc_values, Loc_ref)
{
}

Par_MultiVector::Par_MultiVector(const Par_MultiVector& X)
	: comm(X.comm),
	num_vectors(X.num_vectors),
	Loc(X.Loc)
{
}

Par_MultiVector::Par_MultiVector(Par_MultiVector&& X)
	: comm(X.comm),
	num_vectors(X.num_vectors),
	Loc(X.Loc.num_vectors, X.Loc.size, X.Loc.values, X.Loc.ref)
{
	X.Loc.ref = 1;
}

Par_MultiVector& Par_MultiVector::operator=(const Par_MultiVector& X)
{
	comm = X.comm;
	num_vectors = X.num_vectors;
	Loc = X.Loc;
	return *this;
}

Par_MultiVector& Par_MultiVector::operator=(Par_MultiVector&& X)
{
	Free();

	comm = X.comm;
	num_vectors = X.num_vectors;
	Loc.ref = X.Loc.ref;
	Loc.num_vectors = X.Loc.num_vectors;
	Loc.size = X.Loc.size;
	Loc.values = X.Loc.values;

	X.Loc.ref = 1;

	return *this;
}

void Par_MultiVector::Free()
{
	Loc.Free();
	num_vectors = 0;
}

void Par_MultiVector::Allocate(int m, int n)
{
	num_vectors = m;
	Loc.Allocate(m, n);
}


void Par_MultiVector::Reference(const Par_MultiVector& X)
{
	comm = X.comm;
	num_vectors = X.num_vectors;
	Loc.Reference(X.Loc);
}

const Par_Vector Par_MultiVector::operator()(int j) const
{
	return Par_Vector(comm, Loc.size, Loc.values + j * Loc.size, 1);
}

}